home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / rbbs_pc / aed243a.zip / ANSIED.BAS < prev    next >
BASIC Source File  |  1990-06-10  |  45KB  |  1,351 lines

  1. '*
  2. '*  ANSIED v2.43a
  3. '*---------------------------------------------------------------------------
  4. '*  Full Screen Text Editor for RBBS-PC
  5. '*  QuickBASIC v4.5 Version
  6. '*  06-10-90
  7. '*
  8. '*  v2.1xx ... made it work with RBBS v17
  9. '*  v2.2 ..... fixed some inconsistincies in the code as to # of lines in msg.
  10. '*             Some of the code thought 99 was length, some thought 100.
  11. '*  v2.3 ..... let it work with quoted reply.  No more REDIM of ZOutTxt$
  12. '*  v2.4 ..... removed tabs, margins code to be smaller
  13. '*  v2.41..... fixed bug with loss of bold attribute occasionally
  14. '*  v2.42..... made it work as a v17.3 subroutine.  Added block delete.
  15. '*  v2.43..... Added to: and from:.  Made cursor keys work locally.
  16. '*  v2.43a.... Stupid little bugs fixed
  17. '*
  18. '*  Returns:
  19. '*  ZSubParm  =  1 - Save Message
  20. '*            =  2 - Abort Message
  21. '*            = -1 - Dropped Carrier
  22. '*            = -2 - Sleep Disconnect
  23. '*
  24. '*
  25.  
  26. DECLARE SUB Ansied (T$, S$, L%)
  27. DECLARE SUB ClearScreen ()
  28. DECLARE SUB UpdateStatusLine (How%)
  29. DECLARE SUB MoveCursor (NewRow%, NewCol%)
  30. DECLARE SUB UnString (WasL$, BadString$)
  31. DECLARE SUB UpdateScreen ()
  32. DECLARE SUB Getch (YY$)
  33. DECLARE SUB SaveCursor (Row%, Col%)
  34. DECLARE SUB DisplayMainMenu ()
  35. DECLARE SUB ClearMainMenu ()
  36. DECLARE SUB PutScreen (YY$, Colour%, Bold%)
  37. DECLARE SUB ExecuteMainMenuCommand (CMD$)
  38. DECLARE SUB DeleteCurrentLine (Index%)
  39. DECLARE SUB BackspChar ()
  40. DECLARE SUB CarrRetKey ()
  41. DECLARE SUB NormalChar (YY$)
  42. DECLARE SUB EraseToEOL (LineNumber%, ColNumber%)
  43. DECLARE SUB FindWrap (YY$, WhereToWrap%)
  44. DECLARE SUB Ungetch (X%)
  45. DECLARE SUB DoneWithMsg ()
  46. DECLARE SUB HelpMe ()
  47. DECLARE SUB ReformText (Justify%)
  48. DECLARE SUB LastParaLine (I%, LastLine%, Result%)
  49. DECLARE SUB RightTrim (YY$)
  50.  
  51. ' $INCLUDE: 'RBBS-VAR.MOD'
  52.  
  53. 100   CONST ColorRset = 0
  54.       CONST RedFore = 31
  55.       CONST GreenFore = 32
  56.       CONST YellowFore = 33
  57.       CONST BlueFore = 34
  58.       CONST MagentaFore = 35
  59.       CONST CyanFore = 36
  60.       CONST WhiteFore = 37
  61.       CONST BlueBack = 44
  62.  
  63. 110   CONST ESCKey = 27
  64.       CONST BackspKey = 8
  65.       CONST OtherBackspKey = 127
  66.       CONST CarrRet = 13
  67.       CONST ReformTextKey = 2    ' Ctrl-B
  68.       CONST EndSessionKey = 11   ' Ctrl-K
  69.       CONST HelpKey = 14         ' Ctrl-N
  70.       CONST ReflowTextKey = 15   ' Ctrl-O
  71.       CONST RepaintKey = 16      ' Ctrl-P
  72.       CONST ToggleINSKey = 22    ' Ctrl-V
  73.       CONST LineUpKey = 5        ' Ctrl-E
  74.       CONST LineDownKey = 24     ' Ctrl-X
  75.       CONST ColLeftKey = 19      ' Ctrl-S
  76.       CONST ColRightKey = 4      ' Ctrl-D
  77.       CONST WordLeftKey = 1      ' Ctrl-A
  78.       CONST WordRightKey = 6     ' Ctrl-F
  79.       CONST PageUpKey = 18       ' Ctrl-R
  80.       CONST PageDownKey = 3      ' Ctrl-C
  81.       CONST HomeKey = 23         ' Ctrl-W
  82.       CONST EndKey = 26          ' Ctrl-Z
  83.       CONST LineDeleteKey = 25   ' Ctrl-Y
  84.       CONST CharDeleteKey = 7    ' Ctrl-G
  85.  
  86.       CONST BlankLine$ = ""
  87. 119   CONST Version$ = "v2.43a"
  88.  
  89.       DEFINT A-Z
  90.  
  91. 120   COMMON SHARED /Ansied/ CurrentRow, CurrentCol, TopLine
  92.       COMMON SHARED /Ansied/ OldColour, IsBold, InsertMode
  93.       COMMON SHARED /Ansied/ SoftSpace$, InsOvwPosition
  94.       COMMON SHARED /Ansied/ BlockDelActive, MsgLockLines
  95.       COMMON SHARED /Ansied/ BlockLine1, BlockLine2
  96.       COMMON SHARED /Ansied/ MsgTo$, MsgSubj$
  97.  
  98. '*  AnsiEd
  99. '*----------------------------------------------------------------------------
  100. '*  Main full-screen editor routine
  101. '*
  102. '*
  103.       SUB Ansied (T$, S$, L%) STATIC
  104.  
  105.       '*
  106.       '* ZworkAra$() holds what's currently on the user's screen.
  107.       '* 24 Lines: ZWorkAra$(1) = Menu, Bottom Line = "Line 25"
  108.       '*
  109. 500   REDIM ZWorkAra$(24)
  110.       '*
  111.       '* TopLine is the index into the ZOutTxt$() array that
  112.       '* corresponds to the top of the displayed image, i.e.
  113.       '* what's on line 2 of the user's screen.
  114.       '*
  115.       '*   1,12,23,34,45,56,78
  116.       '*
  117.       TopLine = 1
  118.       SoftSpace$ = CHR$(250)
  119.       InsertMode = ZTrue
  120.       ZLineFeed$ = CHR$(10)
  121.       OldColour = 0
  122.       Bold = ZFalse
  123.       IsBold = 99
  124.       BlockDelActive = ZFalse
  125.       CurrentCol = 0
  126.       CurrentRow = 0
  127.  
  128.       MsgLockLines = L
  129.  
  130.       MsgTo$ = T$
  131.       CALL NameCaps(MsgTo$)
  132.  
  133.       MsgSubj$ = S$
  134.       ZOutTxt$ = ""
  135.       IF LEFT$(MsgSubj$, 3) = "(R)" THEN
  136.          ZOutTxt$ = "(R)"
  137.          MsgSubj$ = MID$(MsgSubj$, 4)
  138.       END IF
  139.       CALL NameCaps(MsgSubj$)
  140.       MsgSubj$ = ZOutTxt$ + MsgSubj$
  141.  
  142.       '*
  143.       '* Initialize the screen array as all blanks
  144.       '*
  145. 510   FOR I = 3 TO 24
  146.          ZWorkAra$(I) = BlankLine$
  147.       NEXT I
  148.  
  149.       '*
  150.       '* Initialize the screen
  151.       '*
  152.       CALL ClearScreen
  153.       CALL UpdateStatusLine(1)
  154.       CALL MoveCursor(3, 1)
  155.       '*
  156.       '* Remove ANSI sequences from the quoted lines
  157.       '*
  158.       IF ZLinesInMsg > 88 THEN
  159.          ZLinesInMsg = 88
  160.       END IF
  161.       IF ZMaxMsgLines > 98 THEN
  162.          ZMaxMsgLines = 98
  163.       END IF
  164.       IF ZLinesInMsg > ZMaxMsgLines THEN
  165.          ZLinesInMsg = ZMaxMsgLines
  166.       END IF
  167.       FOR I = ZLinesInMsg + 1 TO 99
  168.          ZOutTxt$(I) = BlankLine$
  169.       NEXT
  170.       IF ZLinesInMsg <> 0 THEN
  171.          FOR I = 1 TO ZLinesInMsg
  172.             CALL UnString(ZOutTxt$(I), "")
  173.          NEXT
  174.          I! = ZLinesInMsg / 11
  175.          J = FIX(I!)
  176.          IF J = I! THEN
  177.            J = J - 1
  178.          END IF
  179.          TopLine = J * 11 + 1
  180.          J = ZLinesInMsg - TopLine
  181.          CALL MoveCursor(J + 5, 1)
  182.       END IF
  183.       CALL UpdateScreen
  184.  
  185.       '*
  186.       '* Run the Editor
  187.       '*
  188. 520   WHILE ZTrue
  189.  
  190.          CALL Carrier: GOSUB 740
  191.  
  192.          CALL Getch(B$): GOSUB 740
  193.          KeyPressed = ASC(B$)
  194.  
  195.          Index = CurrentRow + TopLine - 3
  196.  
  197.          IF BlockDelActive OR Index <= MsgLockLines OR Index > ZMaxMsgLines THEN
  198. 530         SELECT CASE KeyPressed
  199.                CASE CarrRet
  200.                   IF BlockDelActive THEN
  201.                      BlockDelActive = ZFalse
  202.                      BlockLine2 = Index
  203.                      IF Index < BlockLine1 THEN
  204.                         BlockLine2 = BlockLine1
  205.                         BlockLine1 = Index
  206.                      END IF
  207.                      IF BlockLine1 <= MsgLockLines THEN
  208.                         BlockLine1 = MsgLockLines + 1
  209.                      END IF
  210.                      IF BlockLine2 > ZMaxMsgLines THEN
  211.                         BlockLine2 = ZMaxMsgLines
  212.                      END IF
  213.                      K = 0
  214.                      FOR I = BlockLine2 + 1 TO 99
  215.                         ZOutTxt$(BlockLine1 + K) = ZOutTxt$(I)
  216.                         K = K + 1
  217.                      NEXT I
  218.                      WHILE BlockLine1 + K <= 99
  219.                         ZOutTxt$(BlockLine1 + K) = BlankLine$
  220.                         K = K + 1
  221.                      WEND
  222.                      CALL UpdateScreen
  223.                      CALL UpdateStatusLine(2)
  224.                      CALL MoveCursor(RowSave, ColSave)
  225.                   END IF
  226.                   KeyPressed = 255
  227.  
  228. 540            CASE ESCKey
  229.                   IF BlockDelActive THEN
  230.                      BlockDelActive = ZFalse
  231.                      CALL SaveCursor(RowSave, ColSave)
  232.                      CALL UpdateStatusLine(2)
  233.                      CALL MoveCursor(RowSave, ColSave)
  234.                      KeyPressed = 255
  235.                   END IF
  236.  
  237.                CASE LineUpKey, LineDownKey, PageDownKey, PageUpKey
  238.                   '*
  239.                   '* Up and Down get passed on
  240.                   '*
  241.                CASE ELSE
  242.                   '*
  243.                   '* Ignore the key
  244.                   '*
  245.                   KeyPressed = 255
  246.  
  247.             END SELECT
  248.          END IF
  249.  
  250.          '*
  251.          '* Look for an ANSI escape sequence after an ESC
  252.          '*
  253. 550      IF KeyPressed = ESCKey THEN
  254.             CALL Getch(B$): GOSUB 740
  255.             IF B$ = "[" THEN                    ' ANSI sequence
  256.                CALL Getch(B$): GOSUB 740
  257.                IF B$ = "C" THEN
  258.                   KeyPressed = ColRightKey
  259.                ELSEIF B$ = "D" THEN
  260.                   KeyPressed = ColLeftKey
  261.                ELSEIF B$ = "A" THEN
  262.                   KeyPressed = LineUpKey
  263.                ELSEIF B$ = "B" THEN
  264.                   KeyPressed = LineDownKey
  265.                END IF
  266.             END IF
  267.          END IF
  268.  
  269. 560      SELECT CASE KeyPressed
  270.             CASE ESCKey
  271.                '*
  272.                '* User wants to see main menu
  273.                '*
  274.                CALL SaveCursor(RowSave, ColSave)
  275.                CALL DisplayMainMenu
  276.                CALL MoveCursor(RowSave, ColSave)
  277.                KeyPressed = 255: B$ = ""
  278.                WHILE KeyPressed <> ESCKey
  279.                   CALL Getch(B$): GOSUB 740
  280.                   B$ = UCASE$(B$)
  281.                   KeyPressed = ASC(B$)
  282.                   IF KeyPressed = CarrRet THEN
  283.                      B$ = "H"
  284.                   END IF
  285.                   I = INSTR("HJREIPB" + CHR$(ESCKey), B$)
  286.                   IF I = 7 THEN
  287.                      BlockDelActive = ZTrue
  288.                      BlockLine1 = RowSave + TopLine - 3
  289.                      CALL ClearMainMenu
  290.                      CALL QuickTput(ZEmphasizeOff$, 0)
  291.                      CALL PutScreen("Block Delete: Move cursor to last line to delete and press ENTER   ESC Quits", 99, ZFalse)
  292.                      CALL MoveCursor(RowSave, ColSave)
  293.                      BlockLine2 = 0
  294.                      KeyPressed = ESCKey
  295.                   ELSEIF I <> 0 THEN
  296.                      CALL ExecuteMainMenuCommand(B$): GOSUB 740
  297.                      KeyPressed = ESCKey
  298.                   END IF
  299.                WEND
  300.                CALL MoveCursor(RowSave, ColSave)
  301.  
  302. 570         CASE LineUpKey
  303.                '*
  304.                '* Move the current cursor position up one line
  305.                '*
  306.                IF CurrentRow > 3 THEN
  307.                   CALL MoveCursor(CurrentRow - 1, CurrentCol)
  308.                ELSE
  309.                   IF TopLine <> 1 THEN
  310.                      TopLine = TopLine - 11
  311.                      CALL MoveCursor(CurrentRow + 10, CurrentCol)
  312.                      CALL UpdateScreen
  313.                   END IF
  314.                END IF
  315.  
  316. 580         CASE LineDownKey
  317.                '*
  318.                '* Move the current cursor position down one line
  319.                '*
  320.                IF CurrentRow < 24 THEN
  321.                   CALL MoveCursor(CurrentRow + 1, CurrentCol)
  322.                ELSE
  323.                   IF NOT TopLine = 78 THEN
  324.                      TopLine = TopLine + 11
  325.                      CALL MoveCursor(CurrentRow - 10, CurrentCol)
  326.                      CALL UpdateScreen
  327.                   END IF
  328.                END IF
  329.  
  330. 590         CASE ColLeftKey
  331.                '*
  332.                '* Move the current cursor left one column
  333.                '*
  334.                IF CurrentCol > 1 THEN
  335.                   CALL MoveCursor(CurrentRow, CurrentCol - 1)
  336.                END IF
  337.  
  338. 600         CASE ColRightKey
  339.                '*
  340.                '* Move the current cursor right one column
  341.                '*
  342.                IF CurrentCol < 79 THEN
  343.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  344.                END IF
  345.  
  346. 610         CASE WordRightKey
  347.                '*
  348.                '* Move the current cursor right one word
  349.                '*
  350.                FOR I = CurrentCol TO LEN(ZOutTxt$(Index)) - 1
  351.                   YY$ = MID$(ZOutTxt$(Index), I, 1)
  352.                   ZZ$ = MID$(ZOutTxt$(Index), I + 1, 1)
  353.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  354.                      NewCol = I + 1
  355.                      IF NewCol > 79 THEN
  356.                         NewCol = 79
  357.                      END IF
  358.                      CALL MoveCursor(CurrentRow, NewCol)
  359.                      EXIT FOR
  360.                   END IF
  361.                NEXT I
  362.  
  363. 620         CASE WordLeftKey
  364.                '*
  365.                '* Move the current cursor left one word
  366.                '*
  367.                Found = ZFalse
  368.                FOR I = CurrentCol - 1 TO 2 STEP -1
  369.                   ZZ$ = MID$(ZOutTxt$(Index), I, 1)
  370.                   YY$ = MID$(ZOutTxt$(Index), I - 1, 1)
  371.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  372.                      NewCol = I
  373.                      CALL MoveCursor(CurrentRow, NewCol)
  374.                      Found = ZTrue
  375.                      EXIT FOR
  376.                   END IF
  377.                NEXT I
  378.                IF NOT Found THEN
  379.                   CALL MoveCursor(CurrentRow, 1)
  380.                END IF
  381.  
  382. 630         CASE HomeKey
  383.                '*
  384.                '* Move cursor to the start of the line
  385.                '*
  386.                CALL MoveCursor(CurrentRow, 1)
  387.  
  388. 640         CASE EndKey
  389.                '*
  390.                '* Move cursor to the end of the line
  391.                '*
  392.                IF ZOutTxt$(Index) = STRING$(79, 250) THEN
  393.                   NewCol = 1
  394.                ELSE
  395.                   NewCol = 0
  396.                   FOR I = LEN(ZOutTxt$(Index)) TO 1 STEP -1
  397.                      IF MID$(ZOutTxt$(Index), I, 1) <> SoftSpace$ THEN
  398.                         NewCol = I + 1
  399.                         EXIT FOR
  400.                      END IF
  401.                   NEXT I
  402.                   IF NewCol > 79 THEN
  403.                      NewCol = 79
  404.                   ELSEIF NewCol < 1 THEN
  405.                      NewCol = 1
  406.                   END IF
  407.                END IF
  408.                CALL MoveCursor(CurrentRow, NewCol)
  409.  
  410. 650         CASE PageDownKey
  411.                '*
  412.                '* Move the display one page down
  413.                '*
  414.                TopLine = TopLine + 22
  415.                IF TopLine > 78 THEN
  416.                   TopLine = 78
  417.                END IF
  418.                CALL UpdateScreen
  419.  
  420. 660         CASE PageUpKey
  421.                '*
  422.                '* Move the display one page up
  423.                '*
  424.                TopLine = TopLine - 22
  425.                IF TopLine < 1 THEN
  426.                   TopLine = 1
  427.                END IF
  428.                CALL UpdateScreen
  429.  
  430. 670         CASE LineDeleteKey
  431.                '*
  432.                '* Delete the current line in the file
  433.                '*
  434.                CALL SaveCursor(RowSave, ColSave)
  435.                CALL DeleteCurrentLine(Index)
  436.                CALL MoveCursor(RowSave, ColSave)
  437.  
  438. 680         CASE CharDeleteKey
  439.                '*
  440.                '* Delete the current character
  441.                '*
  442.                IF CurrentCol <= LEN(ZOutTxt$(Index)) THEN
  443.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  444.                   CALL BackspChar
  445.                END IF
  446.  
  447. 690         CASE BackspKey, OtherBackspKey
  448.                '*
  449.                '* Back up one character and destroy it
  450.                '*
  451.                CALL BackspChar
  452.  
  453. 700         CASE CarrRet
  454.                '*
  455.                '* Move to the next line, left column
  456.                '*
  457.                IF NOT Index >= ZMaxMsgLines THEN
  458.                   CALL CarrRetKey
  459.                END IF
  460.  
  461. 710         CASE HelpKey, ReformTextKey, ReflowTextKey, EndSessionKey, ToggleINSKey, RepaintKey
  462.                '*
  463.                '* Execute a main menu command
  464.                '*
  465.                '*          1234567890123456789012
  466.                YY$ = MID$(" J        E  HRP     I", KeyPressed, 1)
  467.                CALL SaveCursor(RowSave, ColSave)
  468.                CALL ExecuteMainMenuCommand(YY$): GOSUB 740
  469.                CALL MoveCursor(RowSave, ColSave)
  470.  
  471.             CASE IS > 127, IS < 32
  472.                '*
  473.                '* Ignore characters above 127 or below 32
  474.                '*
  475. 720         CASE ELSE
  476.                '*
  477.                '* Input was a normal character
  478.                '*
  479.                CALL NormalChar(B$)
  480.  
  481.          END SELECT
  482.       WEND
  483.  
  484. 730   REDIM ZWorkAra$(13)
  485.       EXIT SUB
  486.  
  487.       '*
  488.       '* Test ZSubParm and Exit ANSIED if the carrier dropped
  489.       '*
  490. 740   IF ZSubParm <> 0 THEN
  491.          GOTO 730
  492.       END IF
  493.       RETURN
  494.  
  495.       END SUB         ' Sub AnsiEd
  496.  
  497. '*  BackspChar()
  498. '*----------------------------------------------------------------------------
  499. '*  This routine handles the user entering the backspace key
  500. '*
  501. '*
  502.       SUB BackspChar STATIC
  503. 1200  CALL SaveCursor(RowSave, ColSave)
  504.       Index = TopLine + CurrentRow - 3
  505.       IF Index = MsgLockLines + 1 AND CurrentCol = 1 THEN
  506.          EXIT SUB
  507.       END IF
  508.       AtEndOfLine = CurrentCol > LEN(ZOutTxt$(Index))
  509. 1210  IF CurrentCol > 1 THEN
  510.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 2) + MID$(ZOutTxt$(Index), CurrentCol)
  511.          CALL EraseToEOL(CurrentRow, CurrentCol - 1)
  512.          IF NOT AtEndOfLine THEN
  513.             YY$ = MID$(ZOutTxt$(Index), ColSave - 1)
  514.             CALL MoveCursor(RowSave, ColSave - 1)
  515.             CALL PutScreen(YY$, YellowFore, ZTrue)
  516.          END IF
  517.          CALL MoveCursor(RowSave, ColSave - 1)
  518.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  519.       ELSEIF LEN(ZOutTxt$(Index - 1)) >= ZRightMargin THEN
  520.          '*
  521.          '* Do nothing
  522.          '*
  523. 1220  ELSE
  524.          NewCol = LEN(ZOutTxt$(Index - 1)) + 1
  525.          YY$ = ZOutTxt$(Index)
  526.          CALL UnString(YY$, SoftSpace$)
  527.          ZOutTxt$(Index - 1) = ZOutTxt$(Index - 1) + YY$
  528.          IF LEN(ZOutTxt$(Index - 1)) < ZRightMargin THEN
  529.             CALL DeleteCurrentLine(Index)
  530. 1230     ELSE
  531.             CALL FindWrap(LEFT$(ZOutTxt$(Index - 1), ZRightMargin + 1), I)
  532.             IF I = 0 OR I = 1 THEN
  533.                I = ZRightMargin
  534.             END IF
  535.             ZOutTxt$(Index) = MID$(ZOutTxt$(Index - 1), I + 1)
  536.             ZOutTxt$(Index - 1) = LEFT$(ZOutTxt$(Index - 1), I)
  537.          END IF
  538.          IF RowSave > 3 THEN
  539.             CALL MoveCursor(RowSave - 1, NewCol)
  540.             CALL UpdateScreen
  541.          ELSE
  542.             CALL MoveCursor(RowSave, NewCol)
  543.             CALL Ungetch(LineUpKey)
  544.          END IF
  545.       END IF
  546.       END SUB
  547.  
  548. '*  CarrRetKey()
  549. '*----------------------------------------------------------------------------
  550. '*  This routine handles carriage returns entered in the file
  551. '*
  552. '*
  553.       SUB CarrRetKey STATIC
  554. 1300  Index = CurrentRow + TopLine - 3
  555.       IF Index >= 99 THEN
  556.          EXIT SUB
  557.       END IF
  558.       IF InsertMode THEN         ' Insert a new line
  559.          FOR I = 98 TO Index + 1 STEP -1
  560.             ZOutTxt$(I + 1) = ZOutTxt$(I)
  561.          NEXT I
  562.          IF LEN(ZOutTxt$(Index)) >= CurrentCol THEN
  563.             ZOutTxt$(Index + 1) = MID$(ZOutTxt$(Index), CurrentCol)
  564.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1)
  565.          ELSE
  566.             ZOutTxt$(Index + 1) = BlankLine$
  567.          END IF
  568.          CALL UpdateScreen
  569.       END IF
  570.       IF CurrentRow < 24 THEN
  571.          CALL MoveCursor(CurrentRow + 1, 1)
  572.       ELSE
  573.          CALL MoveCursor(CurrentRow, 1)
  574.          CALL Ungetch(LineDownKey)
  575.       END IF
  576.       END SUB
  577.  
  578. '*  ClearMainMenu()
  579. '*----------------------------------------------------------------------------
  580. '*  This routine clears the main menu from the top line
  581. '*
  582. '*
  583.       SUB ClearMainMenu STATIC
  584. 1400  CALL EraseToEOL(1, 1)
  585.       CALL MoveCursor(1, 1)
  586.       END SUB
  587.  
  588. '*  ClearScreen()
  589. '*----------------------------------------------------------------------------
  590. '*  This routine clears the screen and moves the cursor to row 2, col 1
  591. '*
  592. '*
  593.       SUB ClearScreen STATIC
  594. 1500  FOR I = 1 TO 23
  595.          ZWorkAra$(I) = BlankLine$
  596.       NEXT I
  597.       CALL QuickTput("H", 0)   ' clear screen, column 1, row 3
  598.       ZSubParm = 2
  599.       CALL Line25
  600.       ZSubParm = 0
  601.       CurrentCol = 1
  602.       CurrentRow = 3
  603.       IsBold = 99
  604.       END SUB
  605.  
  606. '*  DeleteCurrentLine()
  607. '*----------------------------------------------------------------------------
  608. '*  This routine deletes the current line on the screen and in the array
  609. '*  ZOutTxt$, and moves the next lower line up one  It then repaints the
  610. '*  affected portion of the screen (from the deleted line down)
  611. '*
  612. '*
  613.       SUB DeleteCurrentLine (Index%) STATIC
  614. 1600  FOR I = Index% TO 98
  615.          ZOutTxt$(I) = ZOutTxt$(I + 1)
  616.       NEXT I
  617.       ZOutTxt$(99) = BlankLine$
  618.       CALL UpdateScreen
  619.       END SUB
  620.  
  621. '*  DisplayMainMenu()
  622. '*----------------------------------------------------------------------------
  623. '*  This routine displays the main menu on the top line
  624. '*
  625. '*
  626.       SUB DisplayMainMenu STATIC
  627. 1700  CALL MoveCursor(1, 1)
  628.       CALL QuickTput(ZEmphasizeOff$, 0)
  629.       YY$ = " [H]elp  E)nd  R)eflow  J)ustify  I)ns/Ovw  P)aint  B)lock Delete   ESC Quits"
  630.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  631.       ZHiLiteOff = ZFalse
  632.       CALL ColorPrompt(YY$)
  633.       CALL PutScreen(YY$, 99, ZTrue)
  634.       IsBold = 99
  635.       END SUB
  636.  
  637. '*  DoneWithMsg()
  638. '*----------------------------------------------------------------------------
  639. '*  This routine is called to save or abort the message
  640. '*
  641. '*
  642.       SUB DoneWithMsg STATIC
  643. 1800  CALL SaveCursor(RowSave, ColSave)
  644.       CALL ClearMainMenu
  645.       CALL QuickTput(ZEmphasizeOff$, 0)
  646.       YY$ = "End Message: S)ave, A)bort, or [C]ontinue? "
  647.       ZHiLiteOff = ZFalse
  648.       CALL ColorPrompt(YY$)
  649.       CALL PutScreen(YY$, 99, ZTrue)
  650.       B$ = " "
  651.       WHILE INSTR("SAC" + CHR$(ESCKey) + CHR$(CarrRet), B$) = 0
  652.          CALL Getch(B$)
  653.          IF ZSubParm <> 0 THEN
  654.             EXIT SUB
  655.          END IF
  656.          B$ = UCASE$(B$)
  657.       WEND
  658. 1810  SELECT CASE B$
  659.          CASE "S"        ' Save Message
  660.             CALL ClearScreen
  661.             '*
  662.             '* Remove trailing blank lines from the message
  663.             '*
  664.             EndOfMsg = ZMaxMsgLines
  665.             FOR I = ZMaxMsgLines TO 1 STEP -1
  666.                IF ZOutTxt$(I) <> BlankLine$ THEN
  667.                   EndOfMsg = I
  668.                   EXIT FOR
  669.                END IF
  670.             NEXT I
  671.             IF I = 0 THEN
  672.                EndOfMsg = 1
  673.             END IF
  674.             FOR I = 1 TO EndOfMsg
  675.                J = INSTR(ZOutTxt$(I), SoftSpace$)
  676.                WHILE J <> 0
  677.                   MID$(ZOutTxt$(I), J, 1) = " "
  678.                   J = INSTR(ZOutTxt$(I), SoftSpace$)
  679.                WEND
  680.             NEXT I
  681.             FOR I = EndOfMsg TO 1 STEP -1
  682.                ZOutTxt$ = RTRIM$(ZOutTxt$)
  683.                IF ZOutTxt$(I) <> BlankLine$ THEN
  684.                   EndOfMsg = I
  685.                   EXIT FOR
  686.                END IF
  687.             NEXT I
  688.             ZLinesInMsg = EndOfMsg
  689.             CALL QuickTput(ZEmphasizeOff$, 0)
  690.             ZSubParm = 1
  691.  
  692. 1820     CASE "A"
  693.             CALL ClearMainMenu
  694.             CALL QuickTput(ZEmphasizeOff$, 0)
  695.             YY$ = "Abort: Are You Sure (Y)es,[N]o)? "
  696.             ZHiLiteOff = ZFalse
  697.             CALL ColorPrompt(YY$)
  698.             CALL PutScreen(YY$, 99, ZTrue)
  699.             CALL Getch(B$)
  700.             IF ZSubParm <> 0 THEN
  701.                B$ = "Y"
  702.             END IF
  703.             IF UCASE$(B$) = "Y" THEN
  704.                CALL ClearScreen
  705.                CALL QuickTput(ZEmphasizeOff$, 0)
  706.                ZSubParm = 2
  707.             END IF
  708.       END SELECT
  709.       END SUB
  710.  
  711. '*  EraseToEOL()
  712. '*----------------------------------------------------------------------------
  713. '*  This routine clears from a position to to the end of that line
  714. '*
  715. '*
  716.       SUB EraseToEOL (LineNumber, ColNumber) STATIC
  717. 1900  CALL SaveCursor(RowSave, ColSave)
  718.       CALL MoveCursor(LineNumber, ColNumber)
  719.       CALL QuickTput("", 0)
  720.       CALL MoveCursor(RowSave, ColSave)
  721.       END SUB
  722.  
  723. '*  ExecuteMainMenuCommand()
  724. '*----------------------------------------------------------------------------
  725. '* This routine executes the passed main menu command
  726. '*
  727. '*
  728.       SUB ExecuteMainMenuCommand (CMD$) STATIC
  729. 2000  ZSubParm = 0
  730.       SELECT CASE CMD$
  731.          CASE "H"
  732.             CALL HelpMe
  733.          CASE "E"
  734.             CALL DoneWithMsg
  735.          CASE "P"
  736.             CALL ClearScreen
  737.             CALL UpdateScreen
  738.          CASE "I"
  739.             InsertMode = NOT InsertMode
  740.          CASE "R"
  741.             CALL ReformText(ZFalse)
  742.          CASE "J"
  743.             CALL ReformText(ZTrue)
  744.       END SELECT
  745.       IsBold = 99
  746.       IF ZSubParm = 0 THEN
  747.          CALL ClearMainMenu
  748.          CALL UpdateStatusLine(1)
  749.       END IF
  750.       END SUB
  751.  
  752. '*  FindWrap()
  753. '*----------------------------------------------------------------------------
  754. '*  This routine finds a place in the string yy$ that could be used as a
  755. '*  place to wrap the line WhereToWrap should be the last position that
  756. '*  remains in the line, ie
  757. '*    set   currentline$ = left$(yy$,wheretowrap)
  758. '*          nextline$    = mid$ (yy$,wheretowrap+1)
  759. '*
  760. '*
  761.       SUB FindWrap (YY$, WhereToWrap) STATIC
  762. 2100  I = LEN(YY$)
  763.       XX$ = " " + SoftSpace$
  764.       '*
  765.       '* Back over "False hits"
  766.       '*
  767.       ZZ$ = MID$(YY$, I, 1)
  768.       WHILE INSTR(XX$, ZZ$) <> 0 AND I <> 1
  769.          I = I - 1
  770.          ZZ$ = MID$(YY$, I, 1)
  771.       WEND
  772.       WHILE INSTR(XX$, ZZ$) = 0 AND I <> 1
  773.          I = I - 1
  774.          ZZ$ = MID$(YY$, I, 1)
  775.       WEND
  776.       WhereToWrap = I
  777.       END SUB
  778.  
  779. '*  Getch()
  780. '*----------------------------------------------------------------------------
  781. '*  This routine reads a character from the user into YY$
  782. '*
  783. '*
  784.       SUB Getch (YY$) STATIC
  785. 2200  ZAutoLogoff! = TIMER + ZWaitBeforeDisconnect
  786.       CALL Carrier
  787.       YY$ = ""
  788.       WHILE ZSubParm <> -1 AND ZSubParm <> -2 AND YY$ = ""
  789.          ZSubParm = 0
  790.          IF LEN(ZCommportStack$) > 0 THEN
  791.             YY$ = LEFT$(ZCommportStack$, 1)
  792.             ZCommportStack$ = MID$(ZCommportStack$, 2)
  793.          ELSE
  794.             IF ZLocalUser THEN
  795.                YY$ = INKEY$
  796.                IF LEN(YY$) = 2 THEN
  797.                   KeyPressed = ASC(RIGHT$(YY$, 1))
  798.                   YY$ = ""
  799.                   SELECT CASE KeyPressed
  800.                      CASE 82                  ' Insert
  801.                         YY$ = CHR$(ToggleINSKey)
  802.                      CASE 83                  ' Delete
  803.                         YY$ = CHR$(CharDeleteKey)
  804.                      CASE 71                  ' Home
  805.                         YY$ = CHR$(HomeKey)
  806.                      CASE 73                  ' PgUp
  807.                         YY$ = CHR$(PageUpKey)
  808.                      CASE 72                  ' Up Arrow
  809.                         YY$ = CHR$(LineUpKey)
  810.                      CASE 80                  ' Down Arrow
  811.                         YY$ = CHR$(LineDownKey)
  812.                      CASE 81                  ' PgDn
  813.                         YY$ = CHR$(PageDownKey)
  814.                      CASE 75                  ' Left Arrow
  815.                         YY$ = CHR$(ColLeftKey)
  816.                      CASE 77                  ' Right Arrow
  817.                         YY$ = CHR$(ColRightKey)
  818.                      CASE 115                 ' Ctrl-Left Arrow
  819.                         YY$ = CHR$(WordLeftKey)
  820.                      CASE 116                 ' Ctrl-Right Arrow
  821.                         YY$ = CHR$(WordRightKey)
  822.                      CASE 79                  ' End
  823.                         YY$ = CHR$(EndKey)
  824.                   END SELECT
  825.                END IF
  826.             ELSE
  827.                CALL FindFKey
  828.                IF ZSubParm >= 0 THEN
  829.                   YY$ = ZKeyPressed$
  830.                   IF YY$ = "" THEN
  831.                      CALL EofComm(Char%)
  832.                      IF Char% = -1 THEN
  833.                         CALL CheckTime(ZAutoLogoff!, Remain!, 1)
  834.                         IF Remain! < 0 THEN
  835.                            CALL UpdtCalr("Sleep disconnect", 1)
  836.                            ZSubParm = -2
  837.                            ZNo = ZTrue
  838.                            ZSleepDisconnect = ZTrue
  839.                         END IF
  840.                      ELSE
  841.                         CALL Carrier
  842.                         IF ZSubParm <> -1 THEN
  843.                            ZSubParm = 0
  844.                            CALL GetCom(YY$)
  845.                         END IF
  846.                      END IF
  847.                   END IF
  848.                END IF
  849.             END IF
  850.          END IF
  851.       WEND
  852.       END SUB
  853.  
  854. '*  HelpMe()
  855. '*----------------------------------------------------------------------------
  856. '*  This routine provides on-line help for the user
  857. '*
  858. '*
  859.       SUB HelpMe STATIC
  860. 2300  CALL SaveCursor(RowSave, ColSave)
  861.       CALL ClearScreen
  862.       CALL QuickTput(ZEmphasizeOff$, 0)
  863.       CALL BufFile(ZHelpPath$ + "ANSIED" + ZHelpExtension$, X)
  864.       OldColour = 0
  865.       IsBold = 99
  866.       CALL ClearScreen
  867.       FOR I = 3 TO 24
  868.          ZWorkAra$(I) = BlankLine$
  869.       NEXT I
  870.       CALL UpdateScreen
  871.       CALL MoveCursor(ColSave, RowSave)
  872.       END SUB
  873.  
  874. '*  LastParaLine()
  875. '*----------------------------------------------------------------------------
  876. '*  This routine returns ZTrue if ZOutTxt$(I) is the last line
  877. '*  in a paragraph
  878. '*
  879. '*
  880.       SUB LastParaLine (I, LastLine, Result) STATIC
  881. 2400  Result = ZFalse
  882.       IF I = LastLine OR I >= ZMaxMsgLines THEN
  883.          Result = ZTrue
  884.       ELSE
  885.          YY$ = ZOutTxt$(I)
  886.          J = INSTR(YY$, ">")
  887.          IF J = 0 THEN
  888.             J = 6
  889.          END IF
  890.          IF J < 5 THEN
  891.             Result = ZTrue
  892.          ELSEIF YY$ = BlankLine$ THEN
  893.             Result = ZTrue
  894.          ELSE
  895.             IF ZOutTxt$(I + 1) = BlankLine$ THEN
  896.                Result = ZTrue
  897.             ELSEIF LEFT$(ZOutTxt$(I + 1), 1) = " " THEN
  898.                Result = ZTrue
  899.             ELSE
  900.                K = INSTR(ZOutTxt$(I + 1), ">")
  901.                IF K <> 0 AND K < 5 THEN
  902.                   Result = ZTrue
  903.                END IF
  904.             END IF
  905.          END IF
  906.       END IF
  907.       END SUB
  908.  
  909. '*  MoveCursor()
  910. '*----------------------------------------------------------------------------
  911. '*  This routine moves the cursor to the position spec'd by newcol and
  912. '*  newrow and tries to do it with the minimum number of Ansi characters
  913. '*
  914. '*
  915.       SUB MoveCursor (NewRow, NewCol) STATIC
  916. 2500  IF CurrentRow = NewRow AND CurrentCol = NewCol THEN
  917.          EXIT SUB
  918.       ELSEIF NewCol = 0 AND NewRow = 0 THEN
  919.          EXIT SUB
  920.       ELSEIF NewCol = 1 AND NewRow = 1 THEN
  921.          YY$ = "f"
  922.       ELSEIF NewCol <> CurrentCol AND NewRow <> CurrentRow THEN
  923.          YY$ = "" + MID$(STR$(NewRow), 2) + ";" + MID$(STR$(NewCol), 2) + "f"
  924.       ELSE
  925.          IF CurrentCol = NewCol THEN           ' Just the row has changed
  926.             I = CurrentRow - NewRow
  927.             C$ = "A"   ' A=Up, B=Down
  928.          ELSE                                   ' Just the column changed
  929.             I = NewCol - CurrentCol
  930.             C$ = "C"   ' C=Left, D=Right
  931.          END IF
  932.          '*
  933.          '* Adjust the direction of the cursor
  934.          '*
  935.          IF I < 0 THEN
  936.             I = -I
  937.             C$ = CHR$(ASC(C$) + 1)
  938.          END IF
  939.          YY$ = ""
  940.          IF I > 1 THEN
  941.             YY$ = YY$ + MID$(STR$(I), 2)
  942.          END IF
  943.          YY$ = YY$ + C$
  944.       END IF
  945.       CALL QuickTput(YY$, 0)
  946.       ZSubParm = 0
  947.       CurrentRow = NewRow
  948.       CurrentCol = NewCol
  949.       END SUB
  950.  
  951. '*  NormalChar()
  952. '*----------------------------------------------------------------------------
  953. '*  This routine handles 'normal' characters entered into the message
  954. '*
  955. '*
  956.       SUB NormalChar (YY$) STATIC
  957.  
  958. 2600  CALL SaveCursor(RowSave, ColSave)
  959.       Index = CurrentRow + TopLine - 3
  960.       CurrentLineBlank = (ZOutTxt$(Index) = BlankLine$)
  961.       LML = LEN(ZOutTxt$(Index))
  962.  
  963.       IF CurrentCol > 79 THEN
  964.          EXIT SUB
  965.       END IF
  966.  
  967.       AtEndOfLine = ZFalse
  968.  
  969.       IF CurrentCol > LML THEN
  970.          ZOutTxt$(Index) = ZOutTxt$(Index) + SPACE$(CurrentCol - LML)
  971.          ZWorkAra$(CurrentRow) = ZWorkAra$(CurrentRow) + SPACE$(CurrentCol - LML)
  972.          LML = LEN(ZOutTxt$(Index))
  973.          AtEndOfLine = ZTrue
  974.       END IF
  975.  
  976. 2610  IF (CurrentCol <= ZRightMargin AND AtEndOfLine) OR (CurrentCol <= ZRightMargin AND NOT InsertMode) THEN
  977.          '*
  978.          '* Single character changed
  979.          '*
  980.          MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  981.          MID$(ZWorkAra$(CurrentRow), CurrentCol, 1) = YY$
  982.          CALL PutScreen(YY$, YellowFore, ZTrue)
  983.  
  984. 2620  ELSEIF (NOT AtEndOfLine AND InsertMode AND CurrentCol <= ZRightMargin AND LML <= ZRightMargin) THEN
  985.          '*
  986.          '* Have to rewrite the screen from the current pos forward
  987.          '*
  988.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  989.  
  990.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  991.  
  992.          CALL EraseToEOL(CurrentRow, CurrentCol)
  993.          ZZ$ = MID$(ZWorkAra$(CurrentRow), CurrentCol)
  994.          CALL PutScreen(ZZ$, YellowFore, ZTrue)
  995.          CALL MoveCursor(RowSave, ColSave + 1)
  996.  
  997. 2630  ELSE
  998.          '*
  999.          '* Wrap the end of the line
  1000.          '*
  1001.          IF NOT AtEndOfLine THEN
  1002.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  1003.             LML = LML + 1
  1004.          ELSE
  1005.             MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  1006.          END IF
  1007.  
  1008.          CALL FindWrap(ZOutTxt$(Index), I)
  1009.          IF I = 0 OR I = 1 THEN
  1010.             I = ZRightMargin
  1011.          END IF
  1012.  
  1013.          ZZ$ = MID$(ZOutTxt$(Index), (I + 1))
  1014.          CALL RightTrim(ZZ$)
  1015.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), I)
  1016.          ' add to the beginning of a new line
  1017.          IF Index <= 98 THEN
  1018.             Index = Index + 1
  1019.          END IF
  1020.          FOR J = 98 TO Index STEP -1
  1021.             ZOutTxt$(J + 1) = ZOutTxt$(J)
  1022.          NEXT J
  1023.          ZOutTxt$(Index) = ZZ$
  1024.  
  1025.          CALL EraseToEOL(CurrentRow, I + 1)        ' do the "easy" line
  1026.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1027.  
  1028.          CALL UpdateScreen
  1029.          IF (ColSave > I) THEN
  1030.             NewCol = ColSave - I + 1
  1031.             IF RowSave <> 24 THEN
  1032.                CALL MoveCursor(RowSave + 1, NewCol)
  1033.             ELSE
  1034.                CALL MoveCursor(RowSave, NewCol)
  1035.                CALL Ungetch(LineDownKey)
  1036.             END IF
  1037.          ELSE
  1038.             CALL MoveCursor(RowSave, ColSave + 1)
  1039.          END IF
  1040.       END IF
  1041.  
  1042.       END SUB
  1043.  
  1044. '*  PutScreen()
  1045. '*----------------------------------------------------------------------------
  1046. '* This routine writes YY$ to the user in the color and
  1047. '* intensity specified
  1048. '*
  1049. '*
  1050.       SUB PutScreen (YY$, Colour, Bold) STATIC
  1051. 2800  ZZ$ = ""
  1052.       IF Colour <> 99 THEN
  1053.          IF (Colour <> OldColour) OR (Bold <> IsBold) THEN
  1054.             ZZ$ = ""
  1055.             IF Bold <> IsBold THEN
  1056.                IF Bold THEN
  1057.                   ZZ$ = ZZ$ + "1;"
  1058.                   IsBold = ZTrue
  1059.                ELSE
  1060.                   ZZ$ = ZZ$ + "0;"
  1061.                   IsBold = ZFalse
  1062.                END IF
  1063.             END IF
  1064.             ZZ$ = ZZ$ + MID$(STR$(Colour), 2)
  1065.             ZZ$ = ZZ$ + "m"
  1066.          END IF
  1067.       END IF
  1068.       ZOutTxt$ = ZZ$ + YY$
  1069.       IF ZLocalUser THEN
  1070.          CALL QuickTput(ZOutTxt$, 0)
  1071.       ELSE
  1072.          ZSubParm = 4
  1073.          CALL Tput
  1074.          ZSubParm = 0
  1075.       END IF
  1076.       IF INSTR(YY$, "") = 0 THEN
  1077.          CurrentCol = CurrentCol + LEN(YY$)
  1078.          IF CurrentCol > 80 THEN
  1079.             CurrentCol = 0
  1080.             CurrentRow = 0
  1081.          END IF
  1082.       ELSE
  1083.          CurrentRow = 0
  1084.          CurrentCol = 0
  1085.       END IF
  1086.       OldColour = Colour
  1087.       Colour = 99
  1088.       END SUB
  1089.  
  1090. '*  ReformText()
  1091. '*----------------------------------------------------------------------------
  1092. '*  This routine reflows the text to the current margins.  Optionally,
  1093. '*  it right justifies all lines by adding "soft spaces"
  1094. '*
  1095. '*
  1096.       SUB ReformText (Justify%) STATIC
  1097.  
  1098. 2900  DIM SpacePlace(80)
  1099.  
  1100.       CALL ClearMainMenu
  1101.       CALL PutScreen("Reformatting... Please Wait.", WhiteFore, ZTrue)
  1102.  
  1103.       LastLine = 1
  1104.       FOR I = ZMaxMsgLines TO 1 STEP -1
  1105.          IF ZOutTxt$(I) <> BlankLine$ THEN
  1106.             LastLine = I
  1107.             EXIT FOR
  1108.          END IF
  1109.       NEXT
  1110.  
  1111.       I = MsgLockLines + 1   ' Read index
  1112.       J = MsgLockLines + 1   ' Write index
  1113.  
  1114.       '*
  1115.       '* Reflow the text to the maximum on a line
  1116.       '*
  1117.       DO WHILE I <= LastLine
  1118.          ZOutTxt$ = ""
  1119.          DO WHILE 1
  1120.             YY$ = ZOutTxt$(I)
  1121.             CALL UnString(YY$, SoftSpace$)
  1122.             IF ZOutTxt$ <> "" AND RIGHT$(ZOutTxt$, 1) <> " " THEN
  1123.                ZOutTxt$ = ZOutTxt$ + " "
  1124.             END IF
  1125.             ZOutTxt$ = ZOutTxt$ + YY$
  1126.             CALL LastParaLine(I, LastLine, Z)
  1127.             IF LEN(ZOutTxt$) > ZRightMargin OR Z THEN
  1128.                IF LEN(ZOutTxt$) > ZRightMargin THEN
  1129.                   CALL FindWrap(LEFT$(ZOutTxt$, ZRightMargin + 1), K)
  1130.                   IF K = 0 OR K = 1 THEN K = ZRightMargin
  1131.                   ZOutTxt$(J) = LEFT$(ZOutTxt$, K)
  1132.                   IF Z THEN
  1133.                      ' Go to the next paragraph
  1134.                      ZOutTxt$(J + 1) = MID$(ZOutTxt$, K + 1)
  1135.                      J = J + 2
  1136.                      I = I + 1
  1137.                      EXIT DO
  1138.                   ELSE
  1139.                      ZOutTxt$(I) = MID$(ZOutTxt$, K + 1)
  1140.                      J = J + 1
  1141.                      EXIT DO
  1142.                   END IF
  1143.                ELSE          ' Z is ZTrue
  1144.                   ZOutTxt$(J) = ZOutTxt$
  1145.                   J = J + 1
  1146.                   I = I + 1
  1147.                   EXIT DO
  1148.                END IF
  1149.             ELSE
  1150.                I = I + 1
  1151.             END IF
  1152.          LOOP
  1153.       LOOP
  1154.  
  1155.       FOR I = J TO 99
  1156.          ZOutTxt$(I) = BlankLine$
  1157.       NEXT
  1158.  
  1159.       LastLine = J - 1
  1160.  
  1161.       '*
  1162.       '* Space out the text on each line
  1163.       '*
  1164.       IF Justify% THEN
  1165.          FOR I = MsgLockLines + 1 TO LastLine
  1166.             CALL LastParaLine(I, LastLine, Z)
  1167.             IF Z THEN
  1168.             ELSE
  1169.                ZOutTxt$ = ZOutTxt$(I)
  1170.                ZOutTxt$ = RTRIM$(ZOutTxt$)
  1171.                '*
  1172.                '* Skip leading spaces on the line
  1173.                '*
  1174.                J = -1
  1175.                FOR K = 1 TO LEN(ZOutTxt$)
  1176.                   IF MID$(ZOutTxt$, K, 1) <> " " THEN
  1177.                      J = K
  1178.                      EXIT FOR
  1179.                   END IF
  1180.                NEXT
  1181.                IF J <> -1 THEN
  1182.                   '*
  1183.                   '* Find out all of the possible places to put spaces
  1184.                   '*
  1185.                   L = 0
  1186.                   M = INSTR(J, ZOutTxt$, " ")
  1187.                   WHILE M <> 0
  1188.                      L = L + 1
  1189.                      SpacePlace(L) = M
  1190.                      M = INSTR(M + 1, ZOutTxt$, " ")
  1191.                   WEND
  1192.                   IF L <> 0 THEN
  1193.                      '*
  1194.                      '* Space out the line.  First add a space to the
  1195.                      '* start of the line, then add to the end.
  1196.                      '*
  1197.                      SpacesToAdd = ZRightMargin - LEN(ZOutTxt$)
  1198.                      M = 1
  1199.                      N = L
  1200.                      DoM = ZTrue
  1201.                      WHILE SpacesToAdd <> 0
  1202.                         IF DoM THEN
  1203.                            Place = SpacePlace(M)
  1204.                            M = M + 1
  1205.                         ELSE
  1206.                            Place = SpacePlace(N)
  1207.                            N = N - 1
  1208.                         END IF
  1209.                         DoM = NOT DoM
  1210.                         ZOutTxt$(I) = LEFT$(ZOutTxt$(I), Place) + SoftSpace$ + MID$(ZOutTxt$(I), Place + 1)
  1211.                         SpacesToAdd = SpacesToAdd - 1
  1212.                         FOR P = 1 TO L
  1213.                            IF SpacePlace(P) > Place THEN
  1214.                               SpacePlace(P) = SpacePlace(P) + 1
  1215.                            END IF
  1216.                         NEXT
  1217.                         IF M = N THEN
  1218.                            M = 1
  1219.                            N = L
  1220.                         END IF
  1221.                      WEND
  1222.                   END IF
  1223.                END IF
  1224.             END IF
  1225.          NEXT
  1226.       END IF
  1227.  
  1228.       CALL UpdateScreen
  1229.  
  1230.       END SUB
  1231.  
  1232. '*  RightTrim()
  1233. '*----------------------------------------------------------------------------
  1234. '*   Removes soft spaces from a string
  1235. '*
  1236. '*
  1237.       SUB RightTrim (YY$) STATIC
  1238. 3000  FOR I = LEN(YY$) TO 1 STEP -1
  1239.          IF MID$(YY$, I, 1) <> SoftSpace$ THEN
  1240.             YY$ = LEFT$(YY$, I)
  1241.             EXIT SUB
  1242.          END IF
  1243.       NEXT I
  1244.       YY$ = ""
  1245.       END SUB
  1246.  
  1247. '*  SaveCursor()
  1248. '*----------------------------------------------------------------------------
  1249. '*  This routine saves the current cursor position
  1250. '*
  1251. '*
  1252.       SUB SaveCursor (Row%, Col%) STATIC
  1253.       Row% = CurrentRow
  1254.       Col% = CurrentCol
  1255.       END SUB
  1256.  
  1257. '*  UnGetch()
  1258. '*----------------------------------------------------------------------------
  1259. '*   Puts a key in the beginning of the keyboard buffer
  1260. '*
  1261. '*
  1262.       SUB Ungetch (X) STATIC
  1263.       ZCommportStack$ = CHR$(X) + ZCommportStack$
  1264.       END SUB
  1265.  
  1266. '*  UnString()
  1267. '*----------------------------------------------------------------------------
  1268. '*  Removes one string from another
  1269. '*
  1270. '*
  1271.       SUB UnString (WasL$, BadString$) STATIC
  1272.       WasI = INSTR(WasL$, BadString$)
  1273.       WHILE WasI <> 0
  1274.          WasL$ = LEFT$(WasL$, WasI - 1) + MID$(WasL$, WasI + LEN(BadString$))
  1275.          WasI = INSTR(WasL$, BadString$)
  1276.       WEND
  1277.       END SUB
  1278.  
  1279. '*  UpdateScreen()
  1280. '*----------------------------------------------------------------------------
  1281. '*  This is one of the most important routines  It compares the arrays
  1282. '*  ZOutTxt$ and ZWorkAra$ and only sends the user the DIFFERENCE between the
  1283. '*  two within the viewing area  In this way all processing can be done on
  1284. '*  ZOutTxt$ and then the screen is updated to reflect the changes. After the
  1285. '*  users screen is updated, ZWorkAra$ is changed to reflect what should be
  1286. '*  on the users' screen The cursor is restored to its original position
  1287. '*
  1288. '*
  1289.       SUB UpdateScreen STATIC
  1290. 3100  CALL SaveCursor(RowSave, ColSave)
  1291.       FOR I = 3 TO 24
  1292.          Index = I + TopLine - 3
  1293.          ScreenLine$ = ZWorkAra$(I)
  1294.          MessageLine$ = ZOutTxt$(Index)
  1295.          LML = LEN(MessageLine$)
  1296.          IF Index = ZMaxMsgLines + 1 THEN
  1297.             CALL EraseToEOL(I, 1)
  1298.             CALL MoveCursor(I, 1)
  1299.             CALL PutScreen("[* End of Message *]", CyanFore, ZFalse)
  1300.             ZWorkAra$(I) = CHR$(EndKey)
  1301.          ELSEIF Index > ZMaxMsgLines + 1 THEN
  1302.             IF ScreenLine$ <> BlankLine$ THEN
  1303.                CALL EraseToEOL(I, 1)
  1304.                ZWorkAra$(I) = BlankLine$
  1305.             END IF
  1306.          ELSEIF MessageLine$ = ScreenLine$ THEN
  1307.             '*
  1308.             '* Screen = What's in message buffer
  1309.             '*
  1310.          ELSEIF MessageLine$ = BlankLine$ OR MessageLine$ = SPACE$(LML) THEN
  1311.             CALL EraseToEOL(I, 1)
  1312.             ZWorkAra$(I) = MessageLine$
  1313.          ELSE
  1314.             CALL MoveCursor(I, 1)
  1315.             YY$ = MessageLine$
  1316.             CALL PutScreen(YY$, YellowFore, ZTrue)
  1317.             CALL EraseToEOL(CurrentRow, CurrentCol)
  1318.             ZWorkAra$(I) = ZOutTxt$(Index)
  1319.          END IF
  1320.       NEXT I
  1321.       CALL MoveCursor(RowSave, ColSave)
  1322.       END SUB
  1323.  
  1324. '*  UpdateStatusLine()
  1325. '*-----------------------------------------------------------------------------
  1326. '*  Rewrites the status line on screen line(s) 1 and 2
  1327. '*
  1328. '*    Input:  How% = 1   - Rewrite both lines
  1329. '*            How% = 2   - Just rewrite top line
  1330. '*
  1331.       SUB UpdateStatusLine (How%) STATIC
  1332. 3200  YY$ = "ANSIED " + Version$ + " by Tom Collins                       * Press ESC Twice for Menu *"
  1333.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  1334.       CALL MoveCursor(1, 1)
  1335.       CALL PutScreen(YY$, BlueFore, ZTrue)
  1336. 3210  IF How% = 1 THEN
  1337.          YY$ = CHR$(205) + " To: " + MsgTo$ + " " + STRING$(3, CHR$(205)) + " Subject: " + MsgSubj$ + " " + STRING$(3, CHR$(205))
  1338.          InsOvwPosition = LEN(YY$)
  1339.          IF InsertMode THEN
  1340.             YY$ = YY$ + " Insert " + STRING$(3, CHR$(205))
  1341.          ELSE
  1342.             YY$ = YY$ + " Overwrite "
  1343.          END IF
  1344.          YY$ = YY$ + STRING$(79 - LEN(YY$), CHR$(205))
  1345.          I = 1
  1346.          CALL MoveCursor(2, I)
  1347.          CALL PutScreen(YY$, WhiteFore, ZFalse)
  1348.       END IF
  1349.       END SUB
  1350.  
  1351.